package com.gitee.wsl.android.ui.recyclerView.adapter

import android.annotation.SuppressLint
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.ConcatAdapter
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver
import com.gitee.wsl.android.ui.recyclerView.adapter.AdapterConfig.Companion.FLAG_MULTI_SELECT_ABLE
import com.gitee.wsl.android.ui.recyclerView.adapter.AdapterConfig.Companion.FLAG_SELECT_ABLE
import com.gitee.wsl.android.ui.recyclerView.adapter.AdapterConfig.Companion.LAYOUT_TYPE_DEFAULT
import com.gitee.wsl.android.ui.recyclerView.adapter.viewholder.CategoryViewHolder
import com.gitee.wsl.android.ui.recyclerView.adapter.viewholder.CreateViewBingHandler
import com.gitee.wsl.android.ui.recyclerView.adapter.viewholder.DefaultViewHolderFactoryImp
import com.gitee.wsl.android.ui.recyclerView.adapter.viewholder.DefaultViewHolderFactoryManager
import com.gitee.wsl.android.ui.recyclerView.adapter.viewholder.ImageTitleDetailViewHolder
import com.gitee.wsl.android.ui.recyclerView.adapter.viewholder.ImageTitleViewHolder
import com.gitee.wsl.android.ui.recyclerView.adapter.viewholder.Subscriber
import com.gitee.wsl.android.ui.recyclerView.adapter.viewholder.TitleViewHolder
import com.gitee.wsl.android.ui.recyclerView.adapter.viewholder.ViewHolderAction
import com.gitee.wsl.android.ui.recyclerView.adapter.viewholder.ViewHolderBindAction
import com.gitee.wsl.android.ui.recyclerView.adapter.viewholder.ViewHolderBindTranAction
import com.gitee.wsl.android.ui.recyclerView.adapter.viewholder.ViewHolderConfig
import com.gitee.wsl.android.ui.recyclerView.adapter.viewholder.ViewHolderFactory
import com.gitee.wsl.android.ui.recyclerView.adapter.viewholder.ViewHolderFactoryBuilder
import com.gitee.wsl.android.ui.recyclerView.adapter.viewholder.ViewHolderFactoryBuilderScope

import com.gitee.wsl.base.ItemFlagManger
import com.gitee.wsl.android.ui.R
import com.gitee.wsl.ext.base.DEFAULT_BASE_FLAG
import com.gitee.wsl.ext.base.eq
import timber.log.Timber


interface BaseAdapterScope<T : Any,AR: com.gitee.wsl.android.ui.recyclerView.adapter.ActionRepository<T>>{
    fun registerViewHolderFactory(viewHolderFactory: ViewHolderFactory<*>)

    fun registerViewHolderFactory(type: Int, layoutId:Int, bindCallback: ViewHolderAction<T, AR>)

    fun registerViewHolderFactory(type: Int, layoutId:Int, bindHandler: (itemView: View, position: Int, payloads: List<Any>, item:T?, config: ViewHolderConfig<T , AR>)->Unit)

    fun <VIEW_BIND> registerViewHolderFactory(type: Int, layoutId:Int, bindHandler: ViewHolderBindTranAction<T,AR,VIEW_BIND>)

    fun <VIEW_BIND> registerViewHolderFactory(type: Int, layoutId:Int,viewBindCreate:View.() -> VIEW_BIND, bindHandler: ViewHolderBindAction<T,AR,VIEW_BIND>)

    /*fun <VIEW_BIND:ViewBinding> registerViewBindingHolderFactory(type:Int = AdapterConfig.LAYOUT_TYPE_DEFAULT,createHolder:(inflater: LayoutInflater, root: ViewGroup, attachToRoot: Boolean) -> VIEW_BIND,
                                                          bindHandler: ViewHolderBindAction<T, AR, VIEW_BIND>)
*/
    /**
     * DSL 风格
     * registerViewHolderFactory<SameViewBinding>{
     *
     *    createBindView(layoutResId=1001) {
     *        SameViewBinding(this)
     *    }
     *
     *    bindViewHolder{viewBinding, position, payloads, item, config ->
     *        viewBinding.textView.text="test"
     *    }
     * }
     **/
    fun <VIEW_BIND> registerViewHolderFactory(viewHolderFactoryBuilder: ViewHolderFactoryBuilderScope<T, AR, VIEW_BIND>.()->Unit)

    fun itemTypeHandler(itemTypeHandler:(position:Int,item:T?,preItem:T?,nextItem:T?,layoutType:Int?)->Int)

    fun sortHandler(sortHandler:Comparator<T>)

    fun selectHandler( isMultiSelect:Boolean=true,selectHandler:SelectHandler<T>)

    fun filter(callback:FilterHandler<T>)

    fun ableFlag(flag:Int)

    fun registerActionRepository(repository: AR)

    fun ableItemFlag(itemFlagManger:AdapterItemFlagManger<T>?)

    fun actionStateConfig(config:(ViewHolderConfig<T, AR>, textview: TextView, position:Int)->Unit)

    /**
     * 一些实现
     */
    fun sampleTitleHolder(type: Int = LAYOUT_TYPE_DEFAULT, bindHandler: (holder: TitleViewHolder, position: Int, payloads: List<Any>, item:T?, config: ViewHolderConfig<T , AR>)->Unit) {
        registerViewHolderFactory(type, R.layout.item_data_title, viewBindCreate = {
            TitleViewHolder(this)
        },bindHandler)
        type.eq(LAYOUT_TYPE_DEFAULT){
            itemTypeHandler{ _, _, _, _, _ ->
                LAYOUT_TYPE_DEFAULT
            }
        }
    }

    fun sampleImageTitleHolder(type: Int = LAYOUT_TYPE_DEFAULT, bindHandler: (holder: ImageTitleViewHolder, position: Int, payloads: List<Any>, item:T?, config: ViewHolderConfig<T , AR>)->Unit) {
        registerViewHolderFactory(type, R.layout.item_data_image_title, viewBindCreate = {
            ImageTitleViewHolder(this)
        },bindHandler)
        type.eq(LAYOUT_TYPE_DEFAULT){
            itemTypeHandler{ _, _, _, _, _ ->
                LAYOUT_TYPE_DEFAULT
            }
        }
    }

    fun sampleCategoryHolder(type: Int = LAYOUT_TYPE_DEFAULT, bindHandler: (holder: CategoryViewHolder, position: Int, payloads: List<Any>, item:T?,config: ViewHolderConfig<T , AR>)->Unit) {
        registerViewHolderFactory(type, R.layout.item_category, viewBindCreate = {
            CategoryViewHolder(this)
        },bindHandler)
        type.eq(LAYOUT_TYPE_DEFAULT){
            itemTypeHandler{ _, _, _, _, _ ->
                LAYOUT_TYPE_DEFAULT
            }
        }
    }

    fun sampleImageTitleDetailHolder(type: Int = LAYOUT_TYPE_DEFAULT, bindHandler: (holder: ImageTitleDetailViewHolder, position: Int, payloads: List<Any>, item:T?, config: ViewHolderConfig<T , AR>)->Unit) {
        registerViewHolderFactory(type, R.layout.item_data_image_title_detail, viewBindCreate = {
            ImageTitleDetailViewHolder(this)
        },bindHandler)
        type.eq(LAYOUT_TYPE_DEFAULT){
            itemTypeHandler{ _, _, _, _, _ ->
                LAYOUT_TYPE_DEFAULT
            }
        }
    }
}

interface ListAdapterScope<T : Any,AR: com.gitee.wsl.android.ui.recyclerView.adapter.ActionRepository<T>>:BaseAdapterScope<T,AR>{

}

interface PagingAdapterScope<T : Any,AR: com.gitee.wsl.android.ui.recyclerView.adapter.ActionRepository<T>>:BaseAdapterScope<T,AR>{

}


interface BuilderAdapterScope<T : Any,AR: com.gitee.wsl.android.ui.recyclerView.adapter.ActionRepository<T>>:ListAdapterScope<T,AR>,PagingAdapterScope<T,AR>{

    fun pagerAdapter(dataEditAble:Boolean=false)

    //fun viewHolderCustom(type: Int, f:ViewBindCustomHandler<T,AR>)
    fun baseAdapter(adapter:RecyclerView.Adapter<*>)

}

class AdapterConfig<T : Any,AR: com.gitee.wsl.android.ui.recyclerView.adapter.ActionRepository<T>>(val diffCallback: DiffUtil.ItemCallback<T>):ViewHolderConfig<T,AR>()  {

    var isPagerAdapter:Boolean=false

    var pagingDataHelper:PagingDateHelperAction<T>?=null

    var selectCallBack:SelectHandler<T>?=null

    var itemTypeCallBack:ItemTypeHandler<T>?=null

    var filterHandler:FilterHandler<T>?=null

    var sortHandler:Comparator<T>?=null

    /*var selectHelper:SelectHelperAction<T>?=null

    var repository: AR?=null

    var itemFlagManger:AdapterItemFlagManger<T>?=null*/

    val viewHolderFactoryCache = DefaultViewHolderFactoryManager<ViewHolderFactory<out RecyclerView.ViewHolder>>()

    fun registerViewHolderFactory(viewHolderFactory: ViewHolderFactory<*>){
        viewHolderFactoryCache.register(viewHolderFactory.getSupportType(),viewHolderFactory)
    }

    companion object{

        const val LAYOUT_TYPE_UNDOWN = -1
        const val LAYOUT_TYPE_LINE_H = 0
        const val LAYOUT_TYPE_LINE_V = 1
        const val LAYOUT_TYPE_STAGE  =10
        const val LAYOUT_TYPE_GRID   =20
        const val LAYOUT_TYPE_TABLE  =30
        const val LAYOUT_TYPE_FLEX   =40

        const val LAYOUT_TYPE_DEFAULT = LAYOUT_TYPE_UNDOWN

        const val FLAG_SELECT_ABLE= DEFAULT_BASE_FLAG shl 1
        const val FLAG_MULTI_SELECT_ABLE= DEFAULT_BASE_FLAG shl 2

    }
}

internal typealias ViewBindCustomHandler<T,AR> = Subscriber<T, AR>.(parent: Subscriber<T,AR>)->Unit

internal typealias FilterHandler<T> = (item:T) -> Boolean

internal typealias SelectHandler<T> = (selectItemList:List<T>)->Unit

internal typealias ItemTypeHandler<T> = (position:Int,item:T?,preItem:T?,nextItem:T?,layoutType:Int?)->Int

internal typealias CreateAdapterHandler<T,TYPE,AR> = (config:AdapterConfig<T,AR>)->TYPE

internal typealias ItemGet<T> = (position: Int)->T?

class DefaultItemCallback<T : Any>: DiffUtil.ItemCallback<T>() {
    override fun areItemsTheSame(oldItem: T, newItem: T): Boolean {
        return oldItem==newItem
    }

    @SuppressLint("DiffUtilEquals")
    override fun areContentsTheSame(oldItem: T, newItem: T): Boolean {
       return oldItem==newItem
    }
}


/**
 * 示例
 *
 * val adapter=AdapterBuilder<SampleData,ActionRepository>(context){
 *
 *    registerViewHolderFactory(type=10,layoutId=sameLayoutId){itemView, position, payloads, item ->
 *        TODO("Not yet implemented")
 *    }
 *
 *    itemTypeHandler{position, item, preItem, nextItem, layoutType ->
 *        TODO("Not yet implemented")
 *    }
 *
 * }.build{ diffCallback, config, factoryCache ->
 *    SameCommandAdapter(diffCallback,config,factoryCache)
 * }
 *
 * adapter.callSameCommand()
 *
 * class SameCommandAdapter<T : Any,ActionRepository>(diffCallback: DiffUtil.ItemCallback<T>,
 *                                   adapterConfig: AdapterConfig<T,ActionRepository>,
 *                                   defaultViewHolderFactoryCache:DefaultViewHolderFactoryManager<ViewHolderFactory<out RecyclerView.ViewHolder>>):ListBuilderAdapter<T,ActionRepository>(diffCallback,adapterConfig,defaultViewHolderFactoryCache){
 *     override fun callSameCommand() {
 *         TODO("Not yet implemented")
 *     }
 * }
 */

class AdapterBuilder<T : Any,AR: com.gitee.wsl.android.ui.recyclerView.adapter.ActionRepository<T>>(val context: Context,
                                                                                                    diffCallback: DiffUtil.ItemCallback<T> = DefaultItemCallback(),
                                                                                                    configCallback:BuilderAdapterScope<T,AR>.()->Unit ):BuilderAdapterScope<T,AR> {
    val config = AdapterConfig<T,AR>(diffCallback)

    var baseAdapter:RecyclerView.Adapter<*>?=null

    private val viewHolderCustomHandler= mutableMapOf<Int,ViewBindCustomHandler<T,AR>>()

    init {
        configCallback(this)
    }

    override fun registerViewHolderFactory(viewHolderFactory: ViewHolderFactory<*>){
        config.registerViewHolderFactory(viewHolderFactory)
    }

    override fun registerViewHolderFactory(
        type: Int,
        layoutId: Int,
        bindCallback: ViewHolderAction<T,AR>
    ) {
        registerViewHolderFactory(DefaultViewHolderFactoryImp.build(type, layoutId, bindCallback))
    }

    override fun registerViewHolderFactory(
        type: Int,
        layoutId: Int,
        bindHandler:(itemView: View, position: Int, payloads: List<Any>, item:T?, config: ViewHolderConfig<T , AR>)->Unit
    ) {
        registerViewHolderFactory(DefaultViewHolderFactoryImp.build(type, layoutId, bindHandler ))
    }

    override fun <VIEW_BIND> registerViewHolderFactory(
        type: Int,
        layoutId: Int,
        bindHandler: ViewHolderBindTranAction<T, AR, VIEW_BIND>
    ) {
        registerViewHolderFactory(DefaultViewHolderFactoryImp.build(type,layoutId,bindHandler))
    }


    override fun <VIEW_BIND> registerViewHolderFactory(
        type: Int,
        layoutId: Int,
        viewBindCreate: CreateViewBingHandler<VIEW_BIND> ,
        bindHandler: ViewHolderBindAction<T, AR, VIEW_BIND>
    ) {
        registerViewHolderFactory(DefaultViewHolderFactoryImp.build(type,layoutId,bindHandler,viewBindCreate))
    }

    override fun <VIEW_BIND> registerViewHolderFactory(viewHolderFactoryBuilder: ViewHolderFactoryBuilderScope<T, AR, VIEW_BIND>.() -> Unit) {
        val holderBuildFactory= ViewHolderFactoryBuilder<T, AR, VIEW_BIND>()
        viewHolderFactoryBuilder(holderBuildFactory)
        registerViewHolderFactory(holderBuildFactory.build())
    }

    /*override fun <VIEW_BIND: ViewBinding> registerViewBindingHolderFactory(
        type: Int,
        createHolder: (inflater: LayoutInflater, root: ViewGroup, attachToRoot: Boolean) -> VIEW_BIND,
        bindHandler: ViewHolderBindAction<T, AR, VIEW_BIND>
    ) {
        registerViewHolderFactory(DefaultBindingViewHolderFactoryImp(type,createHolder,bindHandler))
    }*/

    override fun itemTypeHandler(itemTypeHandler:ItemTypeHandler<T>) {
       config.itemTypeCallBack=itemTypeHandler
    }

    //以下为非必须设置
    override fun ableFlag(flag:Int){
        config.ableFlag(flag)
    }

    override fun actionStateConfig(config: (ViewHolderConfig<T, AR>, textview: TextView, position: Int) -> Unit) {
       this.config.configViewActionState = config
    }

    override fun sortHandler(sortHandler:Comparator<T>){
        config.sortHandler=sortHandler
    }

    override fun selectHandler( isMultiSelect:Boolean,selectHandler:SelectHandler<T>){
        config.ableFlag(if(isMultiSelect) FLAG_MULTI_SELECT_ABLE else FLAG_SELECT_ABLE)
        config.selectCallBack=selectHandler
    }

    override fun filter(callback: FilterHandler<T>) {
        config.filterHandler=callback
    }

    override fun ableItemFlag(itemFlagManger: AdapterItemFlagManger<T>?) {
        config.itemFlagManger = itemFlagManger?:AdapterItemFlagManger()
    }

    override fun pagerAdapter(dataEditAble:Boolean) {
        if(dataEditAble) config.ableFlag(PagingBuilderAdapter.FLAG_PAGING_DATA_EDIT_ABLE)
        config.isPagerAdapter = true
    }

   /* override fun viewHolderCustom(type: Int, f: ViewBindCustomHandler<T,AR>) {
        viewHolderCustomHandler[type]=f
    }*/

    /**
     * 如果调用和Adapter 相关,可以用重写Adapter的 fun getRepository():AR?来返回非null,它的调用等级高
     */
    override fun registerActionRepository(repository: AR) {
        config.repository=repository
    }

    override fun baseAdapter(adapter: RecyclerView.Adapter<*>) {
        baseAdapter = adapter
    }

    fun build():RecyclerView.Adapter<*>{
        if(config.isPagerAdapter) {
            baseAdapter?.let {
                throw java.lang.IllegalArgumentException(" pager mode auto create,no used baseAdapter")
            }
            config.sortHandler?.let{
                Timber.d("current pager mode no support sort,please sort source")
            }
            return PagingBuilderAdapter(config)
        }
        baseAdapter?.let {
              if(baseAdapter is ListAdapter<*,*>)
                  return  ListWarpBuilderAdapter(baseAdapter as ListAdapter<T, RecyclerView.ViewHolder>,config)
              throw java.lang.IllegalArgumentException("baseAdapter:$baseAdapter not support current.")
        }

        return ListWarpBuilderAdapter(EmptyListAdapter(config.diffCallback),config)
    }


    fun <TYPE:RecyclerView.Adapter<*>> build(createAdapterHandler:CreateAdapterHandler<T,TYPE,AR>):TYPE{
        return createAdapterHandler(config)
    }

    /**
     * 用于 扩展
     *
     */

    fun buildListAdapter():ListBuilderAdapter<T,AR>{
         baseAdapter?.let {
            throw java.lang.IllegalArgumentException(" list mode auto create,no used baseAdapter")
        }
        return ListBuilderAdapter(config)
    }

    fun <TYPE:ListAdapter<T, RecyclerView.ViewHolder>> buildListAdapter(createAdapterHandler:CreateAdapterHandler<T,TYPE,AR>):TYPE{
        return createAdapterHandler(config)
    }

    fun buildPagerAdapter():PagingBuilderAdapter<T,AR>{
        baseAdapter?.let {
                throw java.lang.IllegalArgumentException(" pager mode auto create,no used baseAdapter")
        }
        config.sortHandler?.let{
            Timber.d("current pager mode no support sort,please sort source")
        }
       return PagingBuilderAdapter( config)
    }

    fun <TYPE: PagingDataAdapter<T, RecyclerView.ViewHolder>> buildPagerAdapter(createAdapterHandler:CreateAdapterHandler<T,TYPE,AR>):TYPE{
        return createAdapterHandler(config)
    }

}

interface LayoutChangeSet{
    fun layoutChange(layoutType:Int)
}

class AdapterItemFlagManger<T>: ItemFlagManger<T>(){
    lateinit var itemGet:ItemGet<T>

    fun init(itemGet:ItemGet<T>){
        this.itemGet=itemGet
    }

    val observer=object:AdapterDataObserver(){
        override fun onChanged() {
            reset()
        }

        override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
            (0 until itemCount).forEach {
                itemGet(positionStart)?.let { onDataItemRemoved(it) }
            }
        }
    }
}

fun RecyclerView.Adapter<*>.concatOtherAdapter(config: ConcatAdapter.Config= ConcatAdapter.Config.DEFAULT,vararg adapters: RecyclerView.Adapter<*>):ConcatAdapter{
    val concatAdapters= mutableListOf(this)
    concatAdapters.addAll(adapters)
    return ConcatAdapter(config,concatAdapters)
}
